package com.cpms.framework.common.core.caffeine;

import com.github.benmanes.caffeine.cache.stats.CacheStats;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 类描述：缓存工具类，操作缓存
 * @author: gulang
 * @time: 2023/12/8
 */
@Configuration
@Order(2)
@Import(CaffeineConfiguration.class)
public class CaffeineCacheTemplate {
    private final Logger log = LoggerFactory.getLogger(CaffeineCacheTemplate.class);
    @Resource(name = "caffeineCacheManager")
    private CacheManager caffeineCacheManager;

    /**
     * 提取缓存的值
     *
     * @param cacheName
     * @param key
     * @return
     */
    public Object get(String cacheName, Object key) {
        if(!checkCacheName(cacheName)){
            return null;
        }
        if (null == caffeineCacheManager.getCache(cacheName).get(key)) {
            return null;
        }
        return caffeineCacheManager.getCache(cacheName).get(key).get();
    }

    /**
     * if cacheName not exists, throw {@link Exception}
     * <p>
     * if key not exists, create new CaffeineCache.
     * key exists, update it.
     *
     * @param cacheName
     * @param key
     * @param value
     */
    public void set(String cacheName, Object key, Object value) {
        if(!checkCacheName(cacheName)){
            return;
        }
        Cache cache = caffeineCacheManager.getCache(cacheName);
        CaffeineCache caffeineCache = (CaffeineCache) cache;
        caffeineCache.put(key, value);
    }

    /**
     * 查询缓存清单
     *
     * @return
     */
    public Collection<String> listCacheNames() {
        return caffeineCacheManager.getCacheNames();
    }

    /**
     * 检测缓存名称是否注册的
     * @return
     */
    public boolean checkCacheName(String cacheName) {
        Collection<String> cacheNames = listCacheNames();
        boolean registeredName = cacheNames.contains(cacheName);
        if (registeredName) {
            return true;
        }
        try {
            throw new Exception("cache [" + cacheName + "] not exists.");
        }catch (Exception e){
            log.error("check registerName error ={}",e);
        }
        return false;
    }

    /**
     * 查询缓存性能参数
     *
     * @return
     */
    public Map<String, CacheStats> listCachesStats() {
        Map<String, CacheStats> cacheStatses = new HashMap<>();
        Collection<String> cacheNames = listCacheNames();
        cacheNames.forEach(cacheName -> {
            CaffeineCache caffeineCache = (CaffeineCache) caffeineCacheManager.getCache(cacheName);
            com.github.benmanes.caffeine.cache.Cache<Object, Object> cache = caffeineCache.getNativeCache();
            CacheStats cacheStats = cache.stats();
            cacheStatses.put(cacheName, cacheStats);
        });
        return cacheStatses;
    }

    /**
     * 移除某个key缓存
     * <p>
     * if cacheName not exists, throw {@link Exception}
     *
     * @param cacheName
     * @param key
     */
    public void remove(String cacheName, Object key) {
        if(!checkCacheName(cacheName)){
            return;
        }
        Cache cache = caffeineCacheManager.getCache(cacheName);
        cache.evict(key);
    }

    /**
     * 清空某个cacheName 缓存
     * <p>
     * if cacheName not exists, throw {@link Exception }
     *
     * @param cacheName
     */
    public void clear(String cacheName) {
        if(!checkCacheName(cacheName)){
            return;
        }
        Cache cache = caffeineCacheManager.getCache(cacheName);
        cache.clear();
    }
}
